package cn.tedu.medicalmanagementsystem.user.service.impl;

import cn.tedu.medicalmanagementsystem.base.response.JsonResult;
import cn.tedu.medicalmanagementsystem.base.response.StatusCode;
import cn.tedu.medicalmanagementsystem.user.mapper.UserAppointmentMapper;
import cn.tedu.medicalmanagementsystem.user.pojo.dto.AppointmentAddParam;
import cn.tedu.medicalmanagementsystem.user.pojo.entity.UserAppointment;
import cn.tedu.medicalmanagementsystem.user.pojo.vo.UserAppointmentVO;
import cn.tedu.medicalmanagementsystem.user.service.AppointmentService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Optional;

@Slf4j
@Service
public class AppointmentServiceImpl implements AppointmentService {

    @Autowired
    private UserAppointmentMapper userAppointmentMapper;

    @Override
    @Transactional
    public JsonResult createAppointment(AppointmentAddParam param, Long userId) {
        try {
            // 检查必填字段
            if (param == null || param.getEscortId() == null ||
                    param.getAppointmentTime() == null || param.getEndTime() == null) {
                return JsonResult.fail(StatusCode.OPERATION_FAILED, "参数不完整");
            }

            // 检查时间有效性
            if (param.getAppointmentTime().isAfter(param.getEndTime())) {
                return JsonResult.fail(StatusCode.OPERATION_FAILED, "结束时间必须晚于开始时间");
            }

            // 检查陪诊员是否可预约
            if (!isEscortAvailable(param.getEscortId(), param.getAppointmentTime(), param.getEndTime())) {
                return JsonResult.fail(StatusCode.OPERATION_FAILED, "该陪诊员在此时间段已被预约，请选择其他时间");
            }

            // 构建预约对象
            UserAppointment appointment = new UserAppointment();
            BeanUtils.copyProperties(param, appointment);
            appointment.setUserId(userId);

            // 设置默认值
            if (appointment.getStatus() == null) {
                appointment.setStatus("pending");
            }
            if (appointment.getPaymentStatus() == null) {
                appointment.setPaymentStatus("unpaid");
            }
            appointment.setCreateTime(LocalDateTime.now());
            appointment.setUserId(userId);

            // 插入数据库
            int rows = userAppointmentMapper.insert(appointment);
            log.info("插入预约记录影响行数：" + rows);
            if (rows != 1) {
                return JsonResult.fail(StatusCode.OPERATION_FAILED, "预约失败，请稍后再试");
            }
            return JsonResult.ok("预约提交成功，请尽快完成支付");
        } catch (Exception e) {
            log.error("创建预约异常", e);
            return JsonResult.fail(StatusCode.SYSTEM_ERROR, "系统异常，请稍后再试");
        }
    }

    @Override
    public JsonResult<List<UserAppointmentVO>> getUserAppointments(Long userId) {
        try {
            List<UserAppointmentVO> appointments = Optional.ofNullable(userAppointmentMapper.selectByUserId(userId))
                    .orElse(Collections.emptyList());
            return JsonResult.ok(appointments);
        } catch (Exception e) {
            log.error("查询预约记录异常", e);
            return JsonResult.fail(StatusCode.SYSTEM_ERROR, "系统异常，请稍后再试");
        }
    }

    @Override
    public JsonResult<UserAppointmentVO> getAppointmentDetails(Long appointmentId) {
        try {
            UserAppointmentVO appointment = userAppointmentMapper.selectById(appointmentId);
            if (appointment == null) {
                return JsonResult.fail(StatusCode.OPERATION_FAIL, "预约不存在");
            }
            return JsonResult.ok(appointment);
        } catch (Exception e) {
            log.error("获取预约详情异常", e);
            return JsonResult.fail(StatusCode.SYSTEM_ERROR, "系统异常，请稍后再试");
        }
    }

    @Override
    @Transactional
    public JsonResult cancelAppointment(Long appointmentId, Long userId) {
        try {
            UserAppointmentVO appointment = userAppointmentMapper.selectById(appointmentId);
            if (appointment == null) {
                return JsonResult.fail(StatusCode.OPERATION_FAIL, "预约不存在");
            }

            if (!appointment.getUserId().equals(userId)) {
                return JsonResult.fail(StatusCode.OPERATION_FAILED, "操作失败");
            }

            if (!"pending".equals(appointment.getStatus())) {
                return JsonResult.fail(StatusCode.OPERATION_FAILED, "当前状态无法取消预约");
            }

            UserAppointment updateAppointment = new UserAppointment();
            updateAppointment.setId(appointmentId);
            updateAppointment.setStatus("cancelled");

            int rows = userAppointmentMapper.update(updateAppointment);
            if (rows != 1) {
                return JsonResult.fail(StatusCode.OPERATION_FAILED, "取消预约失败");
            }
            return JsonResult.ok("取消预约成功");
        } catch (Exception e) {
            log.error("取消预约异常", e);
            return JsonResult.fail(StatusCode.SYSTEM_ERROR, "系统异常，请稍后再试");
        }
    }

    @Override
    public boolean isEscortAvailable(Long escortId, LocalDateTime appointmentTime, LocalDateTime endTime) {
        try {
            // 参数校验
            if (escortId == null || appointmentTime == null || endTime == null) {
                log.warn("陪诊员可用性检查参数不完整");
                return false;
            }

            // 获取陪诊员已有预约，确保不会返回null
            List<UserAppointmentVO> existingAppointments = Optional.ofNullable(
                            userAppointmentMapper.selectByEscortId(escortId))
                    .orElse(Collections.emptyList());

            // 检查时间冲突
            return existingAppointments.stream()
                    .filter(Objects::nonNull) // 过滤掉可能的null元素
                    .filter(appt -> !"cancelled".equals(appt.getStatus())) // 只考虑未取消的预约
                    .noneMatch(appt -> isTimeOverlap(
                            appt.getAppointmentTime(),
                            appt.getEndTime(),
                            appointmentTime,
                            endTime));
        } catch (Exception e) {
            log.error("检查陪诊员可用性异常", e);
            return false;
        }
    }

    /**
     * 检查两个时间段是否有重叠
     * @param start1 第一个时间段的开始时间
     * @param end1 第一个时间段的结束时间
     * @param start2 第二个时间段的开始时间
     * @param end2 第二个时间段的结束时间
     * @return 如果有重叠返回true，否则返回false
     */
    private boolean isTimeOverlap(LocalDateTime start1, LocalDateTime end1,
                                  LocalDateTime start2, LocalDateTime end2) {
        // 如果有任何一个时间为null，则认为没有重叠
        if (start1 == null || end1 == null || start2 == null || end2 == null) {
            return false;
        }
        return !(end1.isBefore(start2) || end2.isBefore(start1));
    }
}